#pragma once

namespace AVUI {

class Rect3D;
class Point3DCollection;
class Viewport3DVisual;
class Camera;
class Transform3D;

class M3DUtil
{
public:

#pragma region Internal Methods

    static Rect3D ComputeAxisAlignedBoundingBox(Point3DCollection* pPositions);
    static Rect3D ComputeTransformedAxisAlignedBoundingBox(const Rect3D& originalBox, Transform3D* pTransform);
    static Rect3D ComputeTransformedAxisAlignedBoundingBox(const Rect3D& originalBox, const Matrix3D& matrix);
    static Rect3D ComputeTransformedAxisAlignedBoundingBoxAffine(const Rect3D& originalBox, const Matrix3D& matrix);
    static Rect3D ComputeTransformedAxisAlignedBoundingBoxNonAffine(const Rect3D& originalBox, const Matrix3D& matrix);
    static float DegreesToRadians(float degrees);
    static float GetAspectRatio(const Size& viewSize);
    static Matrix GetHomogeneousToViewportTransform(const Rect& viewport);
    static Matrix3D GetHomogeneousToViewportTransform3D(const Rect& viewport);
    static Point GetNormalizedPoint(const Point& point, const Size& size);
    static Matrix3D GetWorldToViewportTransform3D(Camera* pCamera, const Rect& viewport);
    static Matrix3D GetWorldTransformationMatrix(Visual3D* pVisual);
    static Matrix3D GetWorldTransformationMatrix(Visual3D* pVisual3DStart, Viewport3DVisual** ppViewport);
    static Point3D Interpolate(const Point3D& v0, const Point3D& v1, const Point3D& v2, const Point& barycentric);
    static bool IsPointInTriangle(const Point& p, Point* rgTriUVVertices, Point3D* rgTri3DVertices, Point3D* pInters3DPoint);
    static float RadiansToDegrees(float radians);
    static bool TryTransformToViewport3DVisual(Visual3D* pVisual3D, Viewport3DVisual** ppViewport, Matrix3D* pMatrix);

#pragma endregion Internal Methods

#pragma region Private Methods

    static void AddPointToBounds(const Point3D& point, Rect3D* pBounds);

#pragma endregion Private Methods
 

};


}; // namespace AVUI

